import ResItem from "./ResItem";
import ResInterface, { ResCallback, ResType } from "./ResInterface";
/**
 * 1. 负责处理加载逻辑
 * 2. 管理加载项
 * 3. 清理加载项
 * 
 */
export default class ResLoader {

    protected helper: ResInterface = null;

    constructor(helper: ResInterface) {
        this.helper = helper
    }

    protected resCache = {}
    /**
     * 清理单个资源
     * @param url 
     * @param type 
     */
    releaseRes(url: string, type: ResType) {
        let ts = this.getKey(url, type);
        let item = this.resCache[ts];
        if (item) {
            item.releaseAll()
            this.resCache[ts] = null;

        } else {
            console.warn('releaseRes item is null  ts  ', ts)
        }
    }

    /**
    * 删除所有资源
    */
    release() {
        // console.log(' ResLoader release ================== ')
        let resources: string[] = Object.keys(this.resCache);
        for (let index = 0; index < resources.length; index++) {
            const key = resources[index];
            const element: ResItem = this.resCache[key];
            if (element) {
                element.releaseAll();
                this.resCache[key] = null;
            } else {
                // console.warn("ResLoader release url  =  is error  ",key)
            }
        }

    }

    private getKey(url: string, type: ResType) {
        let key = url + type;
        return key;
    }
    /**
     * 同时加载多个资源。
     * @param list 需要加载的资源列表
     * @param type 需要加载的资源类型，要求所有资源统一类型
     * @param func 加载后的回调
     * @param loader 资源加载管理器，默认是全局管理器。
     */
    loadArray(list: Array<string>, type: ResType, func: (err: string, process: number) => void) {
        let resCount = 0;
        for (let index = 0; index < list.length; index++) {
            const element = list[index];
            this.loadRes(element, type, (err) => {
                // 不论是否都加载成功都返回。
                if (err) {
                    console.log(err);
                    func(err, resCount / list.length);
                    return;
                }
                resCount++;
                func(err, resCount / list.length);
            });
        }
    }


    getItem(url: string, type: ResType) {
        let ts = this.getKey(url, type)
        if (this.resCache[ts]) {
            return this.resCache[ts]
        } else {
            let item = new ResItem(this.helper, url, type);
            this.resCache[ts] = item;
        }

    }

    /**
     * 直接缓存已有的资源，比如在脚本中挂载的资源。
     * @param url 
     * @param type 
     * @param res 
     */
    cacheRes(url: string, type: ResType, res: any) {
        let ts = this.getKey(url, type);
        let item: ResItem = this.resCache[ts]
        if (!item) {
            item = new ResItem(this.helper, url, type);
            item.cacheRes(res)
            this.resCache[ts] = item;
        }
    }

    /**
     * 加载单个文件
     * @param url 
     * @param type 
     * @param callback 
     */
    loadRes(url: string, type: ResType, callback: (err: string, res: ResItem) => void) {
        let ts = this.getKey(url, type);
        let item: ResItem = this.resCache[ts]
        // console.log(" loadRes url ", url, ' ts ', ts, ' item ', item);
        if (item && item.isDone()) {
            callback(null, item);
            return;
        } else {
            if (item) {//等待加载成功
                item.addCallback(callback)
                return;
            } else {
                item = new ResItem(this.helper, url, type);
                this.resCache[ts] = item;
                item.addCallback(callback)
            }

        }


        let func: ResCallback = (err: any, res: any) => {
            item.updateLoadCount();
            if (err) {
                if (item.getLoadCount() <= 3) {
                    console.warn(" item.getLoadCount()  =========== ", item.getLoadCount())
                    this.helper.loadRes(url, type, func);
                } else {
                    console.warn(" res load fail url is " + url);
                    this.resCache[ts] = null;
                    // callback(err, null);
                    item.setLoadingFlag(false)
                }
            } else {
                item.cacheRes(res);
                if (this.resCache[ts]) {
                    item.setLoadingFlag(true)
                    // callback(err, item);
                } else {
                    //处理加载完之前已经删除的资源
                    item.subCount();
                }


            }
        }
        this.helper.loadRes(url, type, func);
    }



    /**
     * 获取资源的唯一方式 
     * @param url 
     * @param type 
     */
    getRes(url: string, type: ResType) {
        let ts = this.getKey(url, type)
        let item = this.resCache[ts];
        if (item) {
            return item.getRes();
        } else {
            let res = this.helper.getRes(url, type);
            if (res) { // 如果其他管理器已经加载了资源，直接使用。
                // console.log(' 其他加载器已经加载了次资源 ', url)
                let item = new ResItem(this.helper, url, type);
                item.cacheRes(item)
                this.resCache[ts] = item
                return item.getRes();
            } else {
                console.warn('getRes url ', url, ' ts ', ts)
            }

        }
        return null;
    }

}